package com.ruowei.modules.sys.web;

import com.ruowei.common.error.exception.CommonException;
import com.ruowei.config.ApplicationProperties;
import com.ruowei.config.Constants;
import com.ruowei.modules.sys.service.FileService;
import com.ruowei.modules.sys.utils.CommonUtils;
import com.ruowei.security.CurrentUser;
import com.ruowei.security.UserModel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.imageio.stream.FileImageOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static com.ruowei.modules.sys.utils.FileUploadUtils.picTOSize;

@RestController
@RequestMapping("/api")
@Api(tags = Constants.TAG_FILE)
public class FileResource {

    private final FileService fileService;
    private final ApplicationProperties applicationProperties;

    public FileResource(FileService fileService, ApplicationProperties applicationProperties) {
        this.fileService = fileService;
        this.applicationProperties = applicationProperties;
    }

    @PostMapping("/uploadFiles")
    @ApiOperation(value = "多文件上传")
    public List<String> handleFileUpload(@RequestParam("files") MultipartFile[] files, @ApiIgnore @CurrentUser UserModel userModel) {

        if (files == null || files.length < 1) {
            throw new CommonException("未选择文件上传，失败。");
        }
        //获取存放的根目录
        String uploadDir = applicationProperties.getUploadDir();
        //存放路径
        String dirPath = userModel.getUserCode();
        List<String> filePaths = new ArrayList<>();
        for (MultipartFile file : files) {
            String filename = CommonUtils.getUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));//五个uuid字符+文件名+后缀名
            try {
                String os = System.getProperty("os.name");
                if (file.getBytes().length <= 204800) { //100k到200k之间直接存储

                    File file1 = new File((os.toLowerCase().startsWith("win")) ? uploadDir + dirPath + "\\\\" + filename : uploadDir + dirPath + "/" + filename);
                    File fileParent = file1.getParentFile();
                    if (!fileParent.exists()) {
                        fileParent.mkdirs();
                    }
                    file1.createNewFile();
                    FileImageOutputStream imageOutput = null;
                    imageOutput = new FileImageOutputStream(file1);
                    imageOutput.write(file.getBytes(), 0, file.getBytes().length);
                    imageOutput.close();
                    filePaths.add(applicationProperties.getUploadUrlPrefix() + dirPath + "/" + filename);
                    continue;
                }
                if (os.toLowerCase().startsWith("win")) {
                    picTOSize(file.getBytes(), uploadDir + dirPath + "\\\\" + filename);//xin 系统可以
                } else {
                    picTOSize(file.getBytes(), uploadDir + dirPath + "/" + filename);//linnx
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
            filePaths.add(applicationProperties.getUploadUrlPrefix() + dirPath + "/" + filename);
        }
        return filePaths;
    }

    @GetMapping("/files/{filename:.+}")
    @ApiOperation(value = "获取文件", notes = "作者：李春浩")
    public ResponseEntity<Resource> serveFile(@PathVariable String filename) throws UnsupportedEncodingException {

        Resource file = fileService.loadResource(filename);
        return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename*=UTF-8''" + URLEncoder.encode(filename, "UTF-8"))
            .body(file);
    }

    @GetMapping("/files/downloadAttachment")
    @ApiOperation(value = "下载附件", notes = "作者：李春浩")
    public ResponseEntity<Resource> downloadFile(@RequestParam String url) {

        Resource file = fileService.downloadResource(url);
        return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
            "attachment; filename=\"" + file.getFilename() + "\"").body(file);
    }

    @PostMapping("/files")
    @ApiOperation(value = "上传文件", notes = "作者：李春浩")
    public ResponseEntity<FilePath> handleFileUpload(@RequestParam("file") MultipartFile file,
                                                     @ApiIgnore @CurrentUser UserModel userModel) {

        UserInfo userInfo = new UserInfo(userModel.getId(), userModel.getUserName(), userModel.getUserCode());
        FileService.FileInfo fileInfo = fileService.store(file);
        FilePath filePath = new FilePath(fileInfo.getPath(), fileInfo.getName(), ZonedDateTime.now(), userInfo);

        return ResponseEntity.ok(filePath);
    }

    @PostMapping("/files/multiple")
    @ApiOperation(value = "上传多个文件", notes = "作者：李春浩")
    public ResponseEntity<List<FilePath>> handleFilesUpload(@RequestParam("files") MultipartFile[] files,
                                                            @ApiIgnore @CurrentUser UserModel userModel) {
        List<FilePath> list = new ArrayList<>();
        FilePath filePath;
        for (MultipartFile file : files) {
            UserInfo userInfo = new UserInfo(userModel.getId(), userModel.getUserName(), userModel.getUserCode());
            FileService.FileInfo fileInfo = fileService.store(file);
            filePath = new FilePath(fileInfo.getPath(), fileInfo.getName(), ZonedDateTime.now(), userInfo);
            list.add(filePath);
        }
        return ResponseEntity.ok(list);
    }

    static class FilePath {
        private String path;
        private String fileName;
        private ZonedDateTime time;
        private UserInfo userInfo;

        public FilePath(String path, String fileName, ZonedDateTime time, UserInfo userInfo) {
            this.path = path;
            this.fileName = fileName;
            this.time = time;
            this.userInfo = userInfo;
        }

        public ZonedDateTime getTime() {
            return time;
        }

        public void setTime(ZonedDateTime time) {
            this.time = time;
        }

        public String getFileName() {
            return fileName;
        }

        public void setFileName(String fileName) {
            this.fileName = fileName;
        }

        public UserInfo getUserInfo() {
            return userInfo;
        }

        public void setUserInfo(UserInfo userInfo) {
            this.userInfo = userInfo;
        }

        public String getPath() {
            return path;
        }

        public void setPath(String path) {
            this.path = path;
        }
    }

    static class UserInfo {
        private Long userId;
        private String userName;
        private String userCode;

        public UserInfo(Long userId, String userName, String userCode) {
            this.userId = userId;
            this.userName = userName;
            this.userCode = userCode;
        }

        public Long getUserId() {
            return userId;
        }

        public void setUserId(Long userId) {
            this.userId = userId;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public String getUserCode() {
            return userCode;
        }

        public void setUserCode(String userCode) {
            this.userCode = userCode;
        }
    }
}
